﻿#pragma once

#include "Types.h"
#include <string>

namespace Lisp
{
  class Exception
  {
  public:
    Exception() = default;
    Exception(const std::string &msg) : m_msg(msg) {};

    virtual std::string What() const { return m_msg; }

  private:
    std::string m_msg;
  };

  class EmptyInputException : public Exception
  {
  public:
    EmptyInputException() = default;

    virtual std::string What() const override { return "Empty input"; }
  };

  class RuntimeException : public Exception
  {
  public:
    RuntimeException() = default;
    RuntimeException(const std::string &msg) : Exception(msg) {};
  };

  class ReturnException : public Exception
  {
  public:
    ReturnException(ValPtr value) : m_value(value) {}
    ValPtr GetValue() const { return m_value; }

    virtual std::string What() const override { return "returned"; }

  private:
    ValPtr m_value;
  };

  class BreakException : public Exception
  {
  public:
    BreakException() = default;
    virtual std::string What() const override { return "break"; }
  };

  class ContinueException : public Exception
  {
  public:
    ContinueException() = default;
    virtual std::string What() const override { return "continue"; }
  };
}